<template>
  <n-scrollbar ref="scrollbar" class="w-full h-[calc(100vh-210px)] px-4 py-2" @scroll="HandleScroll">
    <div ref="scrollContent">
      <!-- 加载更多 -->
      <div v-if="IsLoadMore" class="w-full flex flex-row justify-center items-center p-2">
        <n-spin size="small" />
      </div>
      <!-- 列表 -->
      <div v-for="(item, index) in MessageList" :key="item.uuid" class="my-5">
        <!-- 显示时间，如果是第一条消息或者与上一条消息时间间隔大于10分钟则显示 -->
        <div class="message-item-notify" v-if="GetTimeLabel(MessageList, index as number, item)">
          <span>{{ GetTimeLabel(MessageList, index as number, item) }}</span>
        </div>
        <!-- 撤回消息 -->
        <div v-if="item.messageType == MessageType.withdraw" class="message-item-notify">
          <span> {{ item.sendId === user.userId ? "你撤回了一条消息" : "对方撤回一条消息" }}</span>
        </div>
        <!-- 消息item -->
        <div v-else :class="user.userId === item.sendId ? 'flex-row-reverse' : 'flex-row'" class="flex gap-2">
          <!-- 头像 -->
          <n-avatar :src="item.sendId === user.userId ? user.avatar : GetAvtarByCache(item)" />
          <!-- 聊天消息 -->
          <Message :message="item" />
        </div>
      </div>
    </div>
  </n-scrollbar>
</template>

<script lang="ts" setup>
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from "vue";
import { storeToRefs } from "pinia";
import { ChatType, IMessage, MessageType } from "@/types/chat.ts";
import { useChat } from "@/store/modules/chat.ts";
import { useUser } from "@/store/modules/user";
import { useMitt } from "@/hooks/useMitt.ts";
import { GetTimeLabel } from "@/utils/time.ts";
import { NScrollbar, NSpin, NAvatar } from "naive-ui";
import Message from "@/components/Message/index.vue";
import { useCache } from "@/store/modules/cache";
const cache = useCache();
const chat = useChat();
const user = useUser();
const scrollbar = ref();
const scrollContent = ref();
const { MessageList, PageInfo } = storeToRefs(chat);
let observer: MutationObserver | null = null;
let lastScrollTop = ref<number | null>(null);

const IsLoadMore = computed(() => PageInfo.value.page < PageInfo.value.totalPage);
const GetAvtarByCache = computed(() => {
  return (message: IMessage) => {
    if (message.chatType === ChatType.group) {
      let info = cache.GetGroupMemberInfo(chat.ChatObject?.id!, message.sendId);
      return info?.avatar || "";
    }
    return chat.ChatObject?.avatar || "";
  };
});
// 滚动到底部
async function ScrollBottom(smooth: boolean = false) {
  await nextTick();
  if (!scrollbar.value || !scrollContent.value) return;
  const scrollToBottom = () => {
    scrollbar.value!.scrollTo({
      top: scrollContent.value!.scrollHeight,
      behavior: smooth ? "smooth" : "auto",
    });
  };
  scrollToBottom();
  if (observer) {
    observer.disconnect();
    observer = null;
  }
  observer = new MutationObserver(() => {
    scrollToBottom();
  });
  observer.observe(scrollContent.value, {
    childList: true,
    subtree: true,
  });
  setTimeout(() => {
    observer?.disconnect();
    observer = null;
  }, 300);
}

// 处理滚动
async function HandleScroll(event: Event) {
  const target = event.target as HTMLElement;
  const scrollTop = target.scrollTop;
  if (lastScrollTop.value && IsLoadMore.value && lastScrollTop.value > scrollTop && scrollTop <= 30) {
    PageInfo.value.page += 1;
    await chat.LoadMoreMessage();
  }
  lastScrollTop.value = scrollTop;
}

onMounted(async () => {
  await ScrollBottom();
});

onBeforeUnmount(() => {
  if (observer) {
    observer.disconnect();
    observer = null;
  }
});

useMitt.on("scrollBottom", ScrollBottom);
</script>

<style lang="scss" scoped>
.message-item-notify {
  text-align: center;
  color: var(--font-placeholde);
  margin: 15px 0;

  span {
    font-size: 12px;
    background-color: var(--bg-message-time);
    border-radius: 20px;
    padding: 4px 10px;
  }
}
</style>
